// 参考: https://www.jianshu.com/p/b895c22c85af

// 我靠 坑爹的 80个字符 之后  换行覆盖前面内容的 bug 干掉 fit(),不设置cols

// https://blog.csdn.net/qq_31126175/article/details/84346305

<template>
    <div class="console"  id="terminal"></div>
</template>
<script>
import 'xterm/css/xterm.css'
import "xterm/lib/xterm.js";
import { Terminal } from 'xterm'
import {FitAddon} from 'xterm-addon-fit'
import { AttachAddon } from 'xterm-addon-attach'

export default {
  name: 'sshTerminal',
  props: {
    terminal: {
      type: Object,
    //   default: {}
    }
  },
  data () {
    return {
      cols: 10,
      rows: 10,
      term: null,
      ws: null,
      content: {
          operate: '',
          rows: 0,
          cols: 0,
      },
    }
  },
  mounted () {
    this.initSocket()
    window.addEventListener('resize',this.windowChange);
  },
  methods: {
    windowChange(){
        const width = window.innerWidth - 230;
        const height = window.innerHeight - 200;
        this.cols = parseInt(width/9, 10)-10;
        this.rows = parseInt(height/17, 10)
        // console.log(window.innerWidth,window.innerHeight,this.cols,this.rows )
        //前后端的cols(后端叫width)要保持一致
        this.content.operate= 'resize'
        this.content.cols = this.cols
        this.content.rows = this.rows
        console.log("this.ws.readyStatte "+this.ws.readyState)
        if (this.ws.readyState == 1){
          this.ws.send(JSON.stringify(this.content))
        }
        

        // this.term.fit();
        this.term.resize(this.cols, this.rows);
        this.term.scrollToBottom();
    },
    initTerminal() {
      // console.log('pid : ' + this.terminal.pid + ' is on ready')
      // console.log(this.terminal.websocket_url)
      const width = window.innerWidth - 230;
      const height = window.innerHeight - 200;
      this.cols = parseInt(width/9, 10)-10;
      this.rows = parseInt(height/17, 10)
      let terminalContainer = document.getElementById('terminal')
      const term = new Terminal({
        rows: this.rows,	
        cols: this.cols,
        cursorBlink: true, //光标闪烁
      })
      const attachAddon = new AttachAddon(this.ws);
      const  fitAddon = new FitAddon();
      term.loadAddon(attachAddon);
      term.loadAddon(fitAddon);
      
      term.open(terminalContainer)
      // 自己实现json格式的数据发送
      term.onData((data) => {
        console.log("onData",this.ws.readyState)
        if(this.ws.readyState == 3) {
          this.$Message.error(this.terminal.pid + '链接已关闭')
          return
        }
        this.ws.send(
          JSON.stringify({
            operate: "command",
            command: data
          })
        );
      });

      //不调用fit(),按space空格键会退回到首行
      // fitAddon.fit()
      //前后端的cols(后端叫width)要保持一致
      this.content.operate= 'resize'
      this.content.cols = this.cols
      this.content.rows = this.rows
      if (this.ws.readyState == 1){
        this.ws.send(JSON.stringify(this.content))
      }

      // 初始化
      term._initialized = true;
      term.focus();
      this.term = term



    },
    initSocket() {
      let url = this.terminal.websocket_url
      this.ws = new WebSocket(url)
      console.log("initSocket: "+this.ws.readyState)
      if (this.ws.readyState == 0) {
        this.ws.close()
        console.log(this.terminal.pid  + ' 主动close socket')
        this.ws = new WebSocket(url)
        console.log("initSocket1: "+this.ws.readyState)
      }

      this.socketOnClose()
      this.socketOnOpen()
      this.socketOnError()
    },
    socketOnOpen() {
      this.ws.onopen = () => {
        // 链接成功后
        this.initTerminal()
      }
    },
    socketOnClose() {
      this.ws.onclose = () => {
        this.ws.close()
        this.$Message.error(this.terminal.pid + '链接已关闭')
        // console.log(this.terminal.pid  + ' close socket')
        this.term.write("链接已退出")
      }
    },
    socketOnError() {
      this.ws.onerror = () => {
        // console.log(this.terminal.pid + ' socket 链接失败')
        this.$Message.error(this.terminal.pid + ' socket 链接失败')
      }
    }

  },
  beforeDestroy () {
    console.log("destroy")
    this.ws.close()
    this.term.dispose()
  }
}
</script>